"""
MCP管理器 - 负责MCP工具的连接和数据库同步
"""

from typing import List, Dict, Any, Optional, Tuple

from sqlalchemy.orm import Session

from config.logging_config import get_logger
from mcp_tools.mcpClient import mcp_client, MCPToolInfo
from pojo.ai_web_detail_tools_model import AIWebDetailToolsModel
from pojo.ai_web_mcp_tools_model import AIWebMCPToolsModel

logger = get_logger(__name__)


class MCPManager:
    """MCP管理器 - 处理MCP工具的连接和数据同步"""

    def __init__(self):
        self.client = mcp_client

    async def connect_and_sync_tools(self, mcp_id: str, mcp_name: str, json_schema: Dict[str, Any], db: Session) -> \
            Tuple[bool, List[Dict[str, Any]]]:
        """连接MCP服务器并同步工具到数据库"""
        try:
            # 1. 连接MCP服务器
            success = await self.client.connect_from_json_schema(mcp_name, json_schema)
            if not success:
                logger.error(f"Failed to connect to MCP server: {mcp_name}")
                return False, []

            # 2. 获取工具列表
            tools = await self.client.get_tools(mcp_name)
            if not tools:
                logger.warning(f"No tools found for MCP server: {mcp_name}")
                return True, []  # 连接成功但无工具

            # 3. 同步工具到数据库
            synced_tools = await self._sync_tools_to_database(mcp_id, tools, db)

            logger.info(f"Successfully synced {len(synced_tools)} tools for MCP: {mcp_name}")
            return True, synced_tools

        except Exception as e:
            logger.error(f"Error connecting and syncing tools for MCP {mcp_name}: {str(e)}")
            return False, []

    async def _sync_tools_to_database(self, mcp_id: str, tools: List[MCPToolInfo], db: Session) -> List[Dict[str, Any]]:
        """将MCP工具同步到数据库"""
        synced_tools = []

        try:
            # 获取现有的MCP工具
            existing_tools = db.query(AIWebDetailToolsModel).filter(
                AIWebDetailToolsModel.parent_id == mcp_id,
                AIWebDetailToolsModel.tool_type == 2  # MCP工具
            ).all()
            existing_tool_names = {tool.tool_name for tool in existing_tools}

            for tool_info in tools:
                try:
                    # 检查工具是否已存在
                    if tool_info.name in existing_tool_names:
                        # 更新现有工具
                        existing_tool = db.query(AIWebDetailToolsModel).filter(
                            AIWebDetailToolsModel.parent_id == mcp_id,
                            AIWebDetailToolsModel.tool_name == tool_info.name,
                            AIWebDetailToolsModel.tool_type == 2  # MCP工具
                        ).first()

                        if existing_tool:
                            # 更新工具信息
                            existing_tool.description = tool_info.description
                            # 确保server_code被设置
                            if not existing_tool.server_code:
                                existing_tool.server_code = tool_info.server_name
                            existing_tool.set_parameters(
                                self._convert_input_schema_to_parameters(tool_info.input_schema))

                            synced_tools.append({
                                "action": "updated",
                                "tool_name": tool_info.name,
                                "description": tool_info.description,
                                "parameters": existing_tool.get_parameters()
                            })
                            logger.info(f"Updated MCP tool: {tool_info.name}")
                    else:
                        # 创建新工具
                        new_tool = AIWebDetailToolsModel(
                            parent_id=mcp_id,
                            tool_type=2,  # MCP工具
                            tool_name=tool_info.name,
                            server_code=tool_info.server_name,  # MCP工具使用server_name作为server_code
                            description=tool_info.description,
                            is_enabled=True,  # 默认启用
                            parameters=self._convert_input_schema_to_parameters(tool_info.input_schema)
                        )

                        db.add(new_tool)

                        synced_tools.append({
                            "action": "created",
                            "tool_name": tool_info.name,
                            "description": tool_info.description,
                            "parameters": new_tool.get_parameters()
                        })
                        logger.info(f"Created new MCP tool: {tool_info.name}")

                except Exception as e:
                    logger.error(f"Error syncing tool {tool_info.name}: {str(e)}")
                    continue

            # 提交数据库更改
            db.commit()

            return synced_tools

        except Exception as e:
            db.rollback()
            logger.error(f"Error syncing tools to database: {str(e)}")
            return []

    def _convert_input_schema_to_parameters(self, input_schema: Dict[str, Any]) -> List[Dict[str, Any]]:
        """将MCP工具的input_schema转换为我们的参数格式"""
        parameters = []

        try:
            # 处理标准的JSON Schema格式
            if "properties" in input_schema:
                properties = input_schema["properties"]
                required_fields = input_schema.get("required", [])

                for param_name, param_def in properties.items():
                    param_type = param_def.get("type", "string")
                    description = param_def.get("description", "")
                    default_value = param_def.get("default")

                    parameter = {
                        "param_name": param_name,
                        "param_type": param_type,
                        "description": description,
                        "is_required": param_name in required_fields,
                        "default_value": default_value
                    }

                    parameters.append(parameter)

            # 如果schema格式不标准，尝试直接解析
            elif isinstance(input_schema, dict) and input_schema:
                # 简单的fallback处理
                for key, value in input_schema.items():
                    if isinstance(value, dict):
                        parameter = {
                            "param_name": key,
                            "param_type": value.get("type", "string"),
                            "description": value.get("description", ""),
                            "is_required": value.get("required", False),
                            "default_value": value.get("default")
                        }
                        parameters.append(parameter)
                    else:
                        # 最简单的fallback
                        parameter = {
                            "param_name": key,
                            "param_type": "string",
                            "description": str(value) if value else "",
                            "is_required": False,
                            "default_value": None
                        }
                        parameters.append(parameter)

        except Exception as e:
            logger.error(f"Error converting input schema to parameters: {str(e)}")
            # 如果转换失败，返回一个基本参数
            parameters = [{
                "param_name": "input",
                "param_type": "string",
                "description": "Tool input",
                "is_required": False,
                "default_value": None
            }]

        return parameters

    async def refresh_mcp_tools(self, mcp_id: str, mcp_name: str, json_schema: Dict[str, Any], db: Session) -> Tuple[
        bool, List[Dict[str, Any]]]:
        """刷新MCP工具列表"""
        try:
            # 先断开可能存在的连接
            await self.client.disconnect_server(mcp_name)

            # 重新连接并同步
            return await self.connect_and_sync_tools(mcp_id, mcp_name, json_schema, db)

        except Exception as e:
            logger.error(f"Error refreshing MCP tools for {mcp_name}: {str(e)}")
            return False, []

    async def disconnect_mcp(self, mcp_name: str) -> bool:
        """断开MCP连接"""
        try:
            return await self.client.disconnect_server(mcp_name)
        except Exception as e:
            logger.error(f"Error disconnecting MCP {mcp_name}: {str(e)}")
            return False

    def get_connected_servers(self) -> List[str]:
        """获取已连接的服务器列表"""
        return self.client.get_connected_servers()

    async def cleanup(self):
        """清理资源"""
        try:
            await self.client.cleanup()
        except Exception as e:
            logger.error(f"Error during MCP manager cleanup: {str(e)}")

    def get_mcp_tools_from_database(self, db: Session, mcp_id: Optional[str] = None) -> List[Dict[str, Any]]:
        """从数据库获取MCP工具列表"""
        try:
            query = db.query(AIWebDetailToolsModel).filter(
                AIWebDetailToolsModel.tool_type == 2  # MCP工具
            )

            if mcp_id:
                query = query.filter(AIWebDetailToolsModel.parent_id == mcp_id)

            tools = query.all()
            return [tool.to_dict() for tool in tools]

        except Exception as e:
            logger.error(f"Error getting MCP tools from database: {str(e)}")
            return []

    def get_enabled_mcp_tools(self, db: Session, mcp_id: Optional[str] = None) -> List[Dict[str, Any]]:
        """获取启用的MCP工具列表"""
        try:
            query = db.query(AIWebDetailToolsModel).filter(
                AIWebDetailToolsModel.tool_type == 2,  # MCP工具
                AIWebDetailToolsModel.is_enabled == True
            )

            if mcp_id:
                query = query.filter(AIWebDetailToolsModel.parent_id == mcp_id)

            tools = query.all()
            result = []

            for tool in tools:
                tool_dict = tool.to_dict()
                # 获取MCP工具的元信息
                mcp_tool = db.query(AIWebMCPToolsModel).filter(
                    AIWebMCPToolsModel.id == tool.parent_id
                ).first()

                if mcp_tool:
                    tool_dict['mcp_name'] = mcp_tool.mcp_name
                    tool_dict['mcp_status'] = mcp_tool.status
                    tool_dict['access_type'] = mcp_tool.access_type

                result.append(tool_dict)

            return result

        except Exception as e:
            logger.error(f"Error getting enabled MCP tools: {str(e)}")
            return []

    def get_mcp_statistics(self, db: Session) -> Dict[str, int]:
        """获取MCP工具统计信息"""
        try:
            # MCP工具集统计
            total_mcp_count = db.query(AIWebMCPToolsModel).count()
            online_mcp_count = db.query(AIWebMCPToolsModel).filter(
                AIWebMCPToolsModel.status == 1
            ).count()

            # MCP工具详情统计
            total_tools = db.query(AIWebDetailToolsModel).filter(
                AIWebDetailToolsModel.tool_type == 2
            ).count()

            enabled_tools = db.query(AIWebDetailToolsModel).filter(
                AIWebDetailToolsModel.tool_type == 2,
                AIWebDetailToolsModel.is_enabled == True
            ).count()

            # 连接状态统计
            connected_servers = self.get_connected_servers()

            return {
                "total_mcp_count": total_mcp_count,
                "online_mcp_count": online_mcp_count,
                "total_tools": total_tools,
                "enabled_tools": enabled_tools,
                "connected_servers": len(connected_servers)
            }

        except Exception as e:
            logger.error(f"Error getting MCP statistics: {str(e)}")
            return {
                "total_mcp_count": 0,
                "online_mcp_count": 0,
                "total_tools": 0,
                "enabled_tools": 0,
                "connected_servers": 0
            }

    def get_mcp_tools_for_agent(self, db: Session, mcp_ids: List[str]) -> List[Dict[str, Any]]:
        """获取智能体使用的MCP工具列表"""
        try:
            if not mcp_ids:
                return []

            tools = db.query(AIWebDetailToolsModel).filter(
                AIWebDetailToolsModel.parent_id.in_(mcp_ids),
                AIWebDetailToolsModel.tool_type == 2,
                AIWebDetailToolsModel.is_enabled == True
            ).all()

            result = []
            for tool in tools:
                tool_dict = tool.to_dict()
                # 添加MCP信息
                mcp_tool = db.query(AIWebMCPToolsModel).filter(
                    AIWebMCPToolsModel.id == tool.parent_id
                ).first()

                if mcp_tool and mcp_tool.status == 1:  # 只包含上线的MCP工具
                    tool_dict['mcp_name'] = mcp_tool.mcp_name
                    tool_dict['mcp_id'] = mcp_tool.id
                    result.append(tool_dict)

            return result

        except Exception as e:
            logger.error(f"Error getting MCP tools for agent: {str(e)}")
            return []

    async def validate_mcp_tools(self, db: Session, mcp_ids: List[str]) -> Dict[str, bool]:
        """验证MCP工具的可用性"""
        validation_results = {}

        try:
            for mcp_id in mcp_ids:
                mcp_tool = db.query(AIWebMCPToolsModel).filter(
                    AIWebMCPToolsModel.id == mcp_id
                ).first()

                if not mcp_tool:
                    validation_results[mcp_id] = False
                    continue

                # 检查MCP是否在线
                if mcp_tool.status != 1:
                    validation_results[mcp_id] = False
                    continue

                # 检查是否有可用的工具
                has_tools = db.query(AIWebDetailToolsModel).filter(
                    AIWebDetailToolsModel.parent_id == mcp_id,
                    AIWebDetailToolsModel.tool_type == 2,
                    AIWebDetailToolsModel.is_enabled == True
                ).first()

                validation_results[mcp_id] = has_tools is not None

        except Exception as e:
            logger.error(f"Error validating MCP tools: {str(e)}")

        return validation_results


# 全局MCP管理器实例
mcp_manager = MCPManager()
